package com.hzy.orderSystem.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
  @Bean
  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    template.setConnectionFactory(factory);

    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    // key采用String的序列化方式
    template.setKeySerializer(stringRedisSerializer);
    // hash的key也采用String的序列化方式
    template.setHashKeySerializer(stringRedisSerializer);
    // value序列化方式采用jackson
    template.setValueSerializer(jackson2JsonRedisSerializer());
    // hash的value序列化方式采用jackson
    template.setHashValueSerializer(jackson2JsonRedisSerializer());
    template.afterPropertiesSet();
    return template;
  }

  /**
   * json序列化
   *
   * @return
   */
  public RedisSerializer<Object> jackson2JsonRedisSerializer() {
    // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
    Jackson2JsonRedisSerializer<Object> serializer =
        new Jackson2JsonRedisSerializer<Object>(Object.class);
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    serializer.setObjectMapper(mapper);
    return serializer;
  }

  @Bean
  public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
    // 生成一个默认配置，通过config对象即可对缓存进行自定义配置
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
    config =
        config
            // 设置 key为string序列化
            .serializeKeysWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                    new StringRedisSerializer()))
            // 设置value为json序列化
            .serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                    jackson2JsonRedisSerializer()))
            // 不缓存空值
            .disableCachingNullValues()
            // 设置缓存的默认过期时间 30分钟
            .entryTtl(Duration.ofMinutes(30L));

    //        //特殊缓存空间应用不同的配置
    Map<String, RedisCacheConfiguration> map = new HashMap<>();
    //        map.put("provider1", config.entryTtl(Duration.ofMinutes(30L)));//provider1缓存空间过期时间
    // 30分钟
    //        map.put("provider2", config.entryTtl(Duration.ofHours(1L)));//provider2缓存空间过期时间 1小时

    // 使用自定义的缓存配置初始化一个RedisCacheManager
    RedisCacheManager cacheManager =
        RedisCacheManager.builder(connectionFactory)
            .cacheDefaults(config) // 默认配置
            .withInitialCacheConfigurations(map) // 特殊缓存
            .transactionAware() // 事务
            .build();

    return cacheManager;
  }
}
